In modern cloud applications, it has become increasingly popular to separate a web client from server side processing. Web clients are often located in separate domains and reside fully client side without a server component. The client's relationship with the server is similar to that of other non-web clients such as a mobile phone client. In such a setup, the web client often makes explicit calls to a RESTful (REpresentational State Transfer) API (Application Programming Interface) provided by the service's back-end. The credential used for establishing security on the connection is often an access token created by the server, such as a JSON web token (JWT). A JWT can be stored at the client in client-side storage, e.g. in JavaScript LocalStore. A JWT is a client-side credential, i.e. one that is readable by the client, e.g. via a client-side API.
JSON is an open standard defined in RFC7519, RFC7515 and RFC7516. Of these standards, RFC7519 relates to creating JWTs. The JWT is signed by the server's key to enable a client to verify its authenticity. The purpose of a JWT is to allow secure communication between client and server. A simplified form of a JWT might be as follows:
{... header ..}{“iss”: “Some Service”,“iat”: 1478526974,“exp”: 1510062974,“aud”: “test”,“sub”: “johh.smith@example.com”}SIGNATURE
Storing a credential using local storage has a number of advantages. First, it allows better isolation of the client-side code from the server-side component. Second, it prevents a credential from being automatically sent when the client-side browser makes a server request. On the second point, a browser transmitting a credential is susceptible to a vulnerability exploited by cross-site request forgery (CSRF) attacks. For example, when accessing a CSRF attack link, a browser is stimulated automatically to send all existing cookies for that domain to the attacker. CSRF attacks thus exploit the trust that a website has in a user's browser.
However, storing a credential locally also has the disadvantage that the credential is vulnerable to cross-site scripting (XSS) attacks against the web client. An XSS attack enables attackers to inject scripts from a client into webpages viewed by other users. XSS attacks exploit the trust that a user has for a website, i.e., the opposite of a CSRF attack. Compared with traditional web applications, in modern applications using JWTs, the access tokens are long-lived and can be valid for a number of days or weeks, which increases the potential damage that can be caused by a single XSS attack, since the exposed tokens can be used long after the root XSS vulnerability has been fixed.
Traditional web applications use special HyperText Transfer Protocol (HTTP) cookies known as HTTPOnly cookies. An HTTPOnly cookie is a type of HTTP cookie which contains a server-side credential that, on an established client-server communication channel, is sent by the client to the server with every call. Giving a cookie an HTTPOnly attribute directs browsers not to reveal such a cookie other than in response to an HTTP request. In particular, an HTTPOnly cookie cannot be accessed by client-side APIs, such as JavaScript code. Consequently, an HTTPOnly cookie is immune from a normal XSS attack.
However, it is usually not possible to use HTTPOnly cookies to store session identifiers in modern applications, since a client-side API of the RESTful type requires a JWT token to be sent to the client through an authenticating HTTP header, but that is not possible, if the cookie is not accessible to the client-side code. In any case, using HTTPOnly cookies to handle authentication, would open up the server to CSRF attacks, so would require additional countermeasures to be adopted.